    #pragma once

    #include <memory>
    #include <iostream>
    #include <string>
    #include <jsoncpp/json/json.h>

    const std::string ProtSep = " ";
    const std::string LineBreakSep = "\n";

    // "len\nx op y\n"
    // "len\nresult code\n"
    // 添加自描述报头 len代表报文的长度，不包含后面的\n
    // 解决用户区分报文边界问题
    std::string EnCode(const std::string& info)
    {
        std::string message = std::to_string(info.size()) + LineBreakSep + info + LineBreakSep;
        return message;
    }

    // "l"
    // "len"
    // "len\n"
    // "len\nx"
    // "len\nx op "
    // "len\nx op y"
    // "len\nx op y\n"
    // "len\nx op y\n""le"
    // "len\nx op y\n""len\nx"
    // "len\nx op y\n""len\nx op y\n"

    // "len\nresult code\n""len\nresult code\n"
    // 取出报文
    bool DeCode(std::string& message,std::string* info)
    {
        // 读到len
        auto pos = message.find(LineBreakSep);
        if(pos == std::string::npos) return false;

        std::string len = message.substr(0,pos);
        int messagelen = stoi(len);

        // 保证读到完整的报文
        int total = len.size() + messagelen + 2*LineBreakSep.size();
        if(message.size() < total) return false;

        *info = message.substr(pos + LineBreakSep.size());
        // 对已经读完的报文，再message中删除
        message.erase(0,total);

        return true;
    }

    // 请求
    class Request
    {
    public:
        Request()
        {}
        Request(int data_x ,int data_y, char op)
            :_data_x(data_x),_data_y(data_y),_oper(op)
        {}

        void Debug()
        {
            std::cout << _data_x << " " << _oper << " " << _data_y << std::endl;
        }

        void Test()
        {
            _data_x++;
            _data_y++;
        }

        // x op y
        // 序列化
        bool Serialize(std::string* out)
        {
            #ifdef SelfDefine
            // 自己设计的反序列化方案
            *out = std::to_string(_data_x) + ProtSep + _oper + ProtSep + std::to_string(_data_y);
            return true;
            #else
            // 成熟的Json序列化方案
            Json::Value root;
            root["data_x"] = _data_x;
            root["data_y"] = _data_y;
            root["oper"] = _oper;

            Json::FastWriter writer;
            *out = writer.write(root);

            return true;
            #endif
        }
        // x op y
        // 反序列化
        bool Deserialize(const std::string& in)
        {
            #ifdef SelfDefine
            // 自己设计的反序列化方案
            auto pos = in.find(ProtSep);
            if(pos == std::string::npos) return false;
            auto rpos = in.rfind(ProtSep);
            if(rpos == std::string::npos) return false;

            _data_x = stoi(in.substr(0,pos));
            _data_y = stoi(in.substr(rpos + ProtSep.size()));

            std::string op = in.substr(pos+ProtSep.size(),rpos - (pos+ProtSep.size()));
            if(op.size() != 1) return false;
            
            _oper = op[0];
            return true;
            #else
            // 成熟的Json反序列化方案
            Json::Value root;
            Json::Reader reader;
            reader.parse(in,root);

            _data_x = root["data_x"].asInt();
            _data_y = root["data_y"].asInt();
            _oper = root["oper"].asInt();

            return true;
            #endif
        }

        int GetX()
        {
            return _data_x;
        }

        int GetY()
        {
            return _data_y;
        }

        char GetOp()
        {
            return _oper;
        }
    private:
        int _data_x; // 第一个参数
        int _data_y; // 第一个参数
        char _oper;  // 操作符
    }; 

    // 响应
    class Response
    {
    public:
        Response()
            :_result(0),_code(0)
        {}
        Response(int result,int code)
            :_result(result),_code(code)
        {}

        // result code
        // 序列化
        bool Serialize(std::string* out)
        {
            #ifdef SelfDefine
            // 自己设计的序列化方案
            *out = std::to_string(_result) + ProtSep + std::to_string(_code);
            return true;

            #else
            // 成熟的Json序列化方案
            Json::Value root;
            root["result"] = _result;
            root["code"] = _code;

            Json::FastWriter writer;
            *out = writer.write(root);
            
            return true;
            #endif
        }
        // result code
        // 反序列化
        bool Deserialize(const std::string& in)
        {
            #ifdef SelfDefine
            // 自己设计的反序列化方案
            auto pos = in.find(ProtSep);
            if(pos == std::string::npos) return false;

            _result = stoi(in.substr(0,pos));
            _code = stoi(in.substr(pos + ProtSep.size()));

            return true;
            #else
            // 成熟的Json反序列化方案
            Json::Value root;
            Json::Reader reader;
            reader.parse(in,root);

            _result = root["result"].asInt();
            _code = root["code"].asInt();

            return true;
            #endif
        }

        void SetResult(int reslut)
        {
            _result = reslut;
        }

        void SetCode(int code)
        {
            _code = code;
        }

        int GetResult()
        {
            return _result;
        }

        int GetCode()
        {
            return _code;
        }

    private:
        int _result;  // 答案
        int _code;    // 答案是否有效
    };

    // 工厂模式，建造类设计模式
    class Factory
    {
    public:
        // 使用智能指针创建Request对象
        std::shared_ptr<Request> BuildRequest()
        {
            std::shared_ptr<Request> req = std::make_shared<Request>();

            return req;
        }
        std::shared_ptr<Request> BuildRequest(int data_x ,int data_y, char op)
        {
            std::shared_ptr<Request> req = std::make_shared<Request>(data_x,data_y,op);

            return req;
        }

        // 使用智能指针创建Response对象
        std::shared_ptr<Response> BuildResponse()
        {
            std::shared_ptr<Response> resp = std::make_shared<Response>();

            return resp;
        }
        std::shared_ptr<Response> BuildResponse(int result,int code)
        {
            std::shared_ptr<Response> resp = std::make_shared<Response>(result,code);

            return resp;
        }
    };